package stat;

import java.util.List;
import java.util.ArrayList;

public class Stat implements StatObservable {

    private List<StatNotifiable> subscribers;
    private int value;
    private StatType type;
    
    public Stat( StatType st ) {
        type = st;
        value = 0;
        subscribers = new ArrayList<StatNotifiable>();
    }
    
    public Stat( StatType st, int value ) {
        type = st;
        this.value = value;
        subscribers = new ArrayList<StatNotifiable>();
    }
    
    /**
     * return the value of this stat
     * @return
     */
    public int getValue() {
        return value;
    }
    
    /**
     * add the differential to the stat
     * @param differential
     */
    public void update(int differential) {
        setValue(getValue() + differential);
        if(getValue() < 0) {
            setValue(0);
        }
    }
    
    /**
     * return the enum of the stat
     * @return
     */
    public StatType getType() {
    	return type;
    }
    
    /**
     * low level abstraction method to actually change the value
     * @param val
     */
    public void setValue(int val) {
        if(val < 0) {
            val = 0;
        }
        value = val;
        notifyAllNotifiables();
    }
    
    /**
     * increment this value
     */
    public void increment() {
    	setValue(getValue() + 1);
    	notifyAllNotifiables();
    }
    
    /**
     * decrement this value
     * @return
     */
    public boolean decrement() { 
        if(getValue() > 0) {
            setValue(getValue()-1);
            notifyAllNotifiables();
            return true;
        }
        return false;
    }
    
    /**
     * add the given stat to this
     * @param differential
     */
    public void add( Stat differential ) {
        setValue(getValue() + differential.getValue());
        notifyAllNotifiables();
    }
    
    /**
     * add the given int value to this's value
     * @param differential
     */
    public void add( int differential ) {
        setValue(getValue() + differential);
        notifyAllNotifiables();
    }
    
    /**
     * subtract the given int from this's value
     * @param differential
     */
    public void subtract(Stat differential) {
    	setValue(getValue() - differential.getValue());
    	notifyAllNotifiables();
    }
    
    /**
     * register the derived stat to the list of subscribers
     */
    public void register( DerivedStat sn ) {
        subscribers.add(sn);
    }
    
    /**
     * notify all observers there was a change
     */
    public void notifyAllNotifiables() {
        java.util.Iterator<StatNotifiable> iter = subscribers.iterator();
        
        while(iter.hasNext()) {
            iter.next().derive(type, value);
        }
        
    }
    
    public String toString() {
    	return value + "";
    	
    }
}
